#pragma once

#include <iostream>
#include <vector>
#include <map>
#include "public.h"
#include "Log.h"
namespace tinyjson
{
    enum class TinyJsonType
    {
        TINY_JSON_EMPTY,
        TINY_JSON_NULL,
        TINY_JSON_TRUE,
        TINY_JSON_FALSE,
        TINY_JSON_NUMBER,
        TINY_JSON_STRING,
        TINY_JSON_ARRAY,
        TINY_JSON_OBJECT
    };

    class TinyJsonValue
    {
        friend class TinyJsonReader;
        friend std::ostream &operator<<(std::ostream &out, const TinyJsonValue &value);

    private:
        TinyJsonType m_type = TinyJsonType::TINY_JSON_EMPTY;
        struct Container
        {
            Number m_number_value = 0;
            StringPtr m_string_value = nullptr;
            ArrayPtr m_array_value = nullptr;
            ObjectPtr m_object_value = nullptr;
        } m_values;

    public:
        TinyJsonValue();
        TinyJsonValue(Number number);
        TinyJsonValue(const char *src);
        TinyJsonValue(const String &src);
        TinyJsonValue(const Array &vec);
        TinyJsonValue(const Object &obj);

        ~TinyJsonValue(){};

        void set_type(TinyJsonType type);

        TinyJsonType get_type() const;
        String get_null() const;
        String get_false() const;
        String get_true() const;
        Number get_number() const;
        String &get_string() const;
        Array &get_array() const;
        Object &get_object() const;

        Boolean is_null() const;
        Boolean is_true() const;
        Boolean is_false() const;
        Boolean is_number() const;
        Boolean is_string() const;
        Boolean is_array() const;
        Boolean is_object() const;

        void reset();

    public:
        static TinyJsonValuePtr create_tinyjsonvalue();
        static std::ostream &format_value(std::ostream &out, const TinyJsonValue &value);
    };
    std::ostream &operator<<(std::ostream &out, const TinyJsonValue &value);

}
//自定义sqdlog输出类型,例如输出TinyJsonValue对象
//需要重载输出运算符(<<)
template <> struct fmt::formatter<tinyjson::TinyJsonValue> : fmt::ostream_formatter {};